package com.ruoyi.common.wechat;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.framework.web.domain.AjaxResult;
import org.apache.hc.client5.http.fluent.Request;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLEncoder;

@Controller
@RequestMapping("/api/wechat")
public class WechatLoginController {

    private String prefix = "h5";

    @Value("${wechat.appid}")
    private String appid;

    @Value("${wechat.appsecret}")
    private String appsecret;

    @Value("${wechat.redirect-uri}")
    private String redirectUri;

    @GetMapping()
    public String config()
    {
        return prefix + "/index_yonghu_out";
    }

    /**
     * 1. 生成微信授权链接（前端调用此接口获取跳转地址）
     */
    @GetMapping("/getAuthUrl")
    public String getAuthUrl() throws Exception {
        // 微信授权基础地址
        String baseUrl = "https://open.weixin.qq.com/connect/qrconnect";
        // 拼接参数（response_type=code表示授权码模式，scope=snsapi_login表示网站扫码登录）
        String authUrl = String.format(
                "%s?appid=%s&redirect_uri=%s&response_type=code&scope=snsapi_login&state=STATE#wechat_redirect",
                baseUrl,
                appid,
                URLEncoder.encode(redirectUri, "UTF-8")  // 回调地址需URLEncode
        );
        return authUrl;  // 返回授权链接给前端

    }
//
//    @GetMapping("/add")
//    public String add()
//    {
//        return prefix + "/add";
//    }

    /**
     * 2. 用code换取access_token和用户信息（前端回调后调用此接口）
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestParam String code) throws Exception {
        // 步骤1：用code换access_token
        String tokenUrl = String.format(
                "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
                appid, appsecret, code
        );
        String tokenResponse = Request.get(tokenUrl).execute().returnContent().asString();
        JSONObject tokenJson = JSONObject.parseObject(tokenResponse);

        // 检查错误（微信接口失败会返回errcode）
        if (tokenJson.containsKey("errcode")) {
            return AjaxResult.error("获取access_token失败：" + tokenJson.getString("errmsg"));
        }

        // 步骤2：用access_token和openid获取用户信息
        String accessToken = tokenJson.getString("access_token");
        String openid = tokenJson.getString("openid");  // 微信用户唯一标识
        String userInfoUrl = String.format(
                "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",
                accessToken, openid
        );
        String userInfoResponse = Request.get(userInfoUrl).execute().returnContent().asString();
        JSONObject userInfo = JSONObject.parseObject(userInfoResponse);

        // 检查错误
        if (userInfo.containsKey("errcode")) {
            return AjaxResult.error("获取用户信息失败：" + userInfo.getString("errmsg"));
        }

        // 步骤3：自定义登录逻辑（如用openid查询/创建本地用户，生成JWT令牌）
        String username = userInfo.getString("nickname");  // 微信昵称
        String avatar = userInfo.getString("headimgurl");  // 微信头像
        // ... 此处省略：根据openid查询数据库，若不存在则创建新用户
        String jwtToken = generateJwtToken(openid);  // 生成自定义令牌

        return AjaxResult.success("登录成功", new LoginVO(jwtToken, username, avatar, openid));
    }

    // 生成JWT令牌（示例方法，需引入JWT依赖实现）
    private String generateJwtToken(String openid) {
        // 实际项目中使用jjwt等库生成JWT
        return "jwt_" + openid;
    }



    // 登录成功后跳转的前端首页
    private static final String FRONT_INDEX_URL = "http://www.xxx.com/index.html";
    // 登录失败后跳转的前端登录页
    private static final String FRONT_LOGIN_URL = "http://www.xxx.com/login.html";

    /**
     * 微信回调接口（微信授权后会请求此接口）
     * 注意：此接口的URL需配置为微信开放平台的"授权回调域名"下的路径
     * 例如：回调域名配置为 www.xxx.com，则此接口URL为 https://www.xxx.com/wechat/callback
     */
    @GetMapping("/callback")
    public void callback(
            @RequestParam("code") String code,
            @RequestParam("state") String state,
            HttpServletRequest request,
            HttpServletResponse response,
            HttpSession session
    ) throws IOException {
        try {
            // 1. 验证state（防CSRF攻击，与登录页存入session的state比对）
            String storedState = (String) session.getAttribute("wechat_state");
            if (storedState == null || !storedState.equals(state)) {
                // state验证失败，跳转登录页并携带错误信息
                String errorUrl = FRONT_LOGIN_URL + "?error=state验证失败";
                response.sendRedirect(errorUrl);
                return;
            }

            // 2. 用code换取access_token和openid
            String tokenUrl = String.format(
                    "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
                    appid, appsecret, code
            );
            String tokenResponse = Request.get(tokenUrl).execute().returnContent().asString();
            JSONObject tokenJson = JSONObject.parseObject(tokenResponse);

            // 检查微信接口返回的错误（如code无效）
            if (tokenJson.containsKey("errcode")) {
                String errorMsg = tokenJson.getString("errmsg");
                String errorUrl = FRONT_LOGIN_URL + "?error=" + URLEncoder.encode(errorMsg, "UTF-8");
                response.sendRedirect(errorUrl);
                return;
            }

            // 3. 提取access_token和openid
            String accessToken = tokenJson.getString("access_token");
            String openid = tokenJson.getString("openid");

            // 4. 用access_token和openid获取用户信息
            String userInfoUrl = String.format(
                    "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",
                    accessToken, openid
            );
            String userInfoResponse = Request.get(userInfoUrl).execute().returnContent().asString();
            JSONObject userInfo = JSONObject.parseObject(userInfoResponse);

            // 检查用户信息获取错误
            if (userInfo.containsKey("errcode")) {
                String errorMsg = userInfo.getString("errmsg");
                String errorUrl = FRONT_LOGIN_URL + "?error=" + URLEncoder.encode(errorMsg, "UTF-8");
                response.sendRedirect(errorUrl);
                return;
            }

            // 5. 自定义登录逻辑（核心）
            // 5.1 用openid查询数据库，判断用户是否已存在
            // 5.2 若不存在则创建新用户（关联openid）
            // 5.3 生成JWT令牌或session登录状态
            String jwtToken = generateJwtToken(openid, userInfo); // 生成令牌

            // 6. 登录成功，跳转前端首页并携带token（或存入cookie）
            // 注意：生产环境建议用cookie存储token（设置httpOnly和secure）
            String successUrl = FRONT_INDEX_URL + "?token=" + URLEncoder.encode(jwtToken, "UTF-8");
            response.sendRedirect(successUrl);

        } catch (Exception e) {
            // 异常处理：跳转登录页
            String errorUrl = FRONT_LOGIN_URL + "?error=" + URLEncoder.encode("登录异常：" + e.getMessage(), "UTF-8");
            response.sendRedirect(errorUrl);
        } finally {
            // 清除session中的state（仅用一次）
            session.removeAttribute("wechat_state");
        }
    }

    /**
     * 生成JWT令牌（示例方法，需引入JWT依赖）
     */
    private String generateJwtToken(String openid, JSONObject userInfo) {
        // 实际项目中使用jjwt等库生成JWT，包含openid、昵称等信息
        String nickname = userInfo.getString("nickname");
        return "jwt_" + openid + "_" + nickname; // 简化示例
    }
}




